07. Numpy-矩阵处理

矩阵在金融中的核心地位

矩阵(Matrix)是金融数学的核心工具,广泛应用于:

  • 投资组合优化:N只资产的收益率表示为N维向量
  • 协方差矩阵:N×N矩阵描述资产间的风险关系
  • 因子模型:收益率 = 因子载荷 × 因子收益 + 特质收益
  • 期权定价与主成分分析:矩阵运算无处不在

理解矩阵运算是掌握现代投资组合理论(MPT)和CAPM的基础。

矩阵的创建方法

Listing 1
import numpy as np  # 导入NumPy库

# ==================== 方法1:使用二维数组创建矩阵(推荐) ====================
matrix1 = np.array([
    [1, 2, 3],  # 第一行
    [4, 5, 6],  # 第二行
    [7, 8, 9]   # 第三行
])
print('3×3矩阵:')
print(matrix1)
3×3矩阵:
[[1 2 3]
 [4 5 6]
 [7 8 9]]

创建特殊矩阵

Listing 2
import numpy as np

# 单位矩阵:对角线为1,其余为0
identity = np.eye(3)
print('单位矩阵:')
print(identity)

# 零矩阵:2行3列全0
zeros = np.zeros((2, 3))
print('\n零矩阵:')
print(zeros)

# 全1矩阵:2行4列全1
ones = np.ones((2, 4))
print('\n全1矩阵:')
print(ones)
单位矩阵:
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]

零矩阵:
[[0. 0. 0.]
 [0. 0. 0.]]

全1矩阵:
[[1. 1. 1. 1.]
 [1. 1. 1. 1.]]

创建对角矩阵

Listing 3
import numpy as np

# diag函数创建对角矩阵,参数为对角线元素
diag = np.diag([1, 2, 3])
print('对角矩阵:')
print(diag)
对角矩阵:
[[1 0 0]
 [0 2 0]
 [0 0 3]]

在金融中,对角矩阵可用于表示各资产的独立波动率。

矩阵 vs 数组:始终使用 ndarray

特性 np.matrix(已弃用) np.ndarray(推荐)
* 运算符 矩阵乘法 元素乘法
维度 始终2维 可以任意维
状态 已弃用(1.20+) 推荐使用

最佳实践:始终使用 np.ndarray 表示矩阵,使用 @ 运算符进行矩阵乘法。

点积(Dot Product)的数学定义

两个向量 \(\mathbf{a}\)\(\mathbf{b}\) 的点积为:

\[ \large{\mathbf{a} \cdot \mathbf{b} = \sum_{i=1}^{n} a_i b_i = a_1b_1 + a_2b_2 + \cdots + a_nb_n} \]

金融含义:点积用于计算加权平均,如投资组合收益率:

\[ \large{R_p = \sum_{i=1}^{n} w_i R_i = \mathbf{w} \cdot \mathbf{R}} \]

其中 \(\mathbf{w}\) 是权重向量,\(\mathbf{R}\) 是收益率向量。

⭐ 实战:使用点积计算投资组合日收益率

Listing 4
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
import numpy as np  # 导入NumPy数值计算库
#使用列表定义5月26日收益率数据 return_0526、权重数据 weight。
return_0526=[0.0172,0.0243,-0.0029,0.0021]
weight=[0.15,0.20,0.25,0.4]  # 定义列表weight
#计算投资组合日收益率
return_daily=np.dot(return_0526,weight).round(3)
print(f'投资组合5月26日收益率为:{return_daily}')  # 输出投资组合5月26日收益率为
投资组合5月26日收益率为:0.008

点积的深层含义

  • 几何意义\(\mathbf{a} \cdot \mathbf{b} = \|\mathbf{a}\| \|\mathbf{b}\| \cos\theta\)
  • 投资组合收益\(\sum w_i R_i\)
  • 因子收益\(\sum \beta_i F_i\)
  • 相似度度量:可衡量两个投资组合的相似程度

矩阵乘法的数学定义

矩阵 \(\mathbf{A}\)\(m \times n\))与 \(\mathbf{B}\)\(n \times p\))的乘积 \(\mathbf{C}\)\(m \times p\)):

\[ \large{c_{ij} = \sum_{k=1}^{n} a_{ik} b_{kj}} \]

重要性质

  • 不满足交换律\(\mathbf{AB} \neq \mathbf{BA}\)
  • 满足结合律\((\mathbf{AB})\mathbf{C} = \mathbf{A}(\mathbf{BC})\)
  • 维度要求\(\mathbf{A}\) 的列数必须等于 \(\mathbf{B}\) 的行数

矩阵乘法的三种实现方法

Listing 5
import numpy as np

A = np.array([[1, 2, 3], [4, 5, 6]])   # 2×3矩阵
B = np.array([[7, 8], [9, 10], [11, 12]])  # 3×2矩阵

# 方法1: @运算符(推荐,Python 3.5+)
C1 = A @ B
print('方法1 - @运算符:')
print(C1)

# 方法2: np.matmul()函数
C2 = np.matmul(A, B)
print('\n方法2 - matmul函数:')
print(C2)

# 方法3: np.dot()函数
C3 = np.dot(A, B)
print('\n方法3 - dot函数:')
print(C3)

print(f'\n结果一致: {np.array_equal(C1, C2) and np.array_equal(C2, C3)}')
方法1 - @运算符:
[[ 58  64]
 [139 154]]

方法2 - matmul函数:
[[ 58  64]
 [139 154]]

方法3 - dot函数:
[[ 58  64]
 [139 154]]

结果一致: True

金融应用:多期投资组合收益

Listing 6
import numpy as np

# 3只股票在4个交易日的收益率矩阵(每行一只股票,每列一个交易日)
returns = np.array([
    [0.01, 0.02, -0.01, 0.03],   # 股票A
    [0.02, 0.01, 0.03, -0.01],   # 股票B
    [-0.01, 0.03, 0.02, 0.04]    # 股票C
])

# 投资组合权重:A 30%、B 50%、C 20%
weights = np.array([0.3, 0.5, 0.2])

# 矩阵乘法:权重(1×3) × 收益率(3×4) = 组合收益(1×4)
portfolio_returns = weights @ returns
print(f'投资组合每日收益率: {portfolio_returns}')

# 累计收益率
cumulative_return = np.prod(1 + portfolio_returns) - 1
print(f'期间累计收益率: {cumulative_return:.4%}')
投资组合每日收益率: [0.011 0.017 0.016 0.012]
期间累计收益率: 5.7174%

协方差矩阵:金融风险管理的核心

对于随机向量 \(\mathbf{X}\),协方差矩阵 \(\mathbf{\Sigma}\) 的元素为:

\[ \large{\Sigma_{ij} = \text{Cov}(X_i, X_j) = E[(X_i - \mu_i)(X_j - \mu_j)]} \]

三大性质

  • 对称性\(\Sigma_{ij} = \Sigma_{ji}\)
  • 半正定性\(\mathbf{a}^T\mathbf{\Sigma}\mathbf{a} \geq 0\)
  • 对角线元素\(\Sigma_{ii} = \text{Var}(X_i)\)

计算协方差矩阵与相关系数矩阵

Listing 7
import numpy as np

np.random.seed(42)
returns = np.random.randn(100, 3) * 0.02  # 100天×3只股票的随机收益率

# 协方差矩阵
cov_matrix = np.cov(returns, rowvar=False)
print('协方差矩阵:')
print(cov_matrix)

# 相关系数矩阵
corr_matrix = np.corrcoef(returns, rowvar=False)
print('\n相关系数矩阵:')
print(corr_matrix)
协方差矩阵:
[[ 2.72117409e-04 -1.57105634e-05 -4.43202407e-05]
 [-1.57105634e-05  3.83454758e-04 -5.39437601e-05]
 [-4.43202407e-05 -5.39437601e-05  4.95427395e-04]]

相关系数矩阵:
[[ 1.         -0.04863585 -0.12070741]
 [-0.04863585  1.         -0.12376394]
 [-0.12070741 -0.12376394  1.        ]]

从协方差矩阵推导相关系数矩阵

\[ \large{\text{Corr}(X, Y) = \frac{\text{Cov}(X, Y)}{\sigma_X \cdot \sigma_Y}} \]

Listing 8
import numpy as np

np.random.seed(42)
returns = np.random.randn(100, 3) * 0.02
cov_matrix = np.cov(returns, rowvar=False)
corr_matrix = np.corrcoef(returns, rowvar=False)

# 标准差向量
std_devs = np.sqrt(np.diag(cov_matrix))
# 外积构造分母矩阵
corr_from_cov = cov_matrix / np.outer(std_devs, std_devs)
print('从协方差计算的相关系数矩阵:')
print(corr_from_cov)

print(f'\n两种方法一致: {np.allclose(corr_matrix, corr_from_cov)}')
从协方差计算的相关系数矩阵:
[[ 1.         -0.04863585 -0.12070741]
 [-0.04863585  1.         -0.12376394]
 [-0.12070741 -0.12376394  1.        ]]

两种方法一致: True

投资组合方差:马科维茨核心公式

\[ \large{\sigma_p^2 = \mathbf{w}^T \mathbf{\Sigma} \mathbf{w} = \sum_{i=1}^{n}\sum_{j=1}^{n} w_i w_j \sigma_{ij}} \]

  • \(\mathbf{w}\):资产权重向量
  • \(\mathbf{\Sigma}\):协方差矩阵
  • \(\sigma_p^2\):投资组合方差

矩阵运算计算投资组合方差

Listing 9
import numpy as np

# 3只股票的协方差矩阵
cov_matrix = np.array([
    [0.0100, 0.0018, 0.0011],
    [0.0018, 0.0081, 0.0009],
    [0.0011, 0.0009, 0.0064]
])

weights = np.array([0.3, 0.5, 0.2])  # A 30%, B 50%, C 20%

# 矩阵运算:wΣw'
portfolio_var = weights @ cov_matrix @ weights.T
portfolio_std = np.sqrt(portfolio_var)

print(f'投资组合方差: {portfolio_var:.6f}')
print(f'投资组合标准差(波动率): {portfolio_std:.4%}')
投资组合方差: 0.004033
投资组合标准差(波动率): 6.3506%

分散化效应:组合风险 < 加权平均风险

Listing 10
import numpy as np

cov_matrix = np.array([
    [0.0100, 0.0018, 0.0011],
    [0.0018, 0.0081, 0.0009],
    [0.0011, 0.0009, 0.0064]
])
weights = np.array([0.3, 0.5, 0.2])

portfolio_std = np.sqrt(weights @ cov_matrix @ weights.T)
individual_stds = np.sqrt(np.diag(cov_matrix))
weighted_avg_std = np.sum(weights * individual_stds)

print(f'加权平均标准差: {weighted_avg_std:.4%}')
print(f'组合标准差:     {portfolio_std:.4%}')
print(f'风险降低:       {(weighted_avg_std - portfolio_std) / weighted_avg_std:.2%}')
# 体现了"不要把鸡蛋放在同一个篮子里"的原理
加权平均标准差: 9.1000%
组合标准差:     6.3506%
风险降低:       30.21%

线性方程组求解:\(\mathbf{Ax} = \mathbf{b}\)

金融中许多问题可转化为线性方程组:

  • 因子收益计算:从资产收益反推因子收益
  • 套利定价理论(APT):求解无风险组合权重
  • 状态估计:Kalman滤波中的状态更新

求解因子收益(APT应用)

Listing 11
import numpy as np

# 因子载荷矩阵:3只资产对3个因子的敏感度
A = np.array([
    [1.2, 0.8, 0.5],  # 资产1
    [0.9, 1.1, 0.3],  # 资产2
    [0.7, 0.6, 0.9]   # 资产3
])

b = np.array([0.08, 0.06, 0.07])  # 资产超额收益率

# 求解因子收益:Ax = b
factor_returns = np.linalg.solve(A, b)
print('因子收益率:')
print(f'  因子1: {factor_returns[0]:.4%}')
print(f'  因子2: {factor_returns[1]:.4%}')
print(f'  因子3: {factor_returns[2]:.4%}')

# 验证
b_reconstructed = A @ factor_returns
print(f'\n验证通过: {np.allclose(b, b_reconstructed)}')
因子收益率:
  因子1: 4.7480%
  因子2: 0.5570%
  因子3: 3.7135%

验证通过: True

矩阵的秩与逆:核心概念

矩阵可逆的充要条件

  • \(\det(\mathbf{A}) \neq 0\)(行列式不为零)
  • \(\text{rank}(\mathbf{A}) = n\)(满秩)
  • \(\mathbf{Ax} = \mathbf{0}\) 只有零解

逆矩阵性质\(\mathbf{A} \times \mathbf{A}^{-1} = \mathbf{I}\)

矩阵的秩与逆运算

Listing 12
import numpy as np

A = np.array([[4, 7], [2, 6]])
print('矩阵A:')
print(A)

# 行列式
det_A = np.linalg.det(A)
print(f'\n行列式: {det_A:.4f}')

# 秩
rank_A = np.linalg.matrix_rank(A)
print(f'秩: {rank_A}')

# 逆矩阵
A_inv = np.linalg.inv(A)
print('\n逆矩阵 A^(-1):')
print(A_inv)

# 验证 A × A^(-1) = I
identity = A @ A_inv
print(f'\n是否为单位矩阵: {np.allclose(identity, np.eye(2))}')
矩阵A:
[[4 7]
 [2 6]]

行列式: 10.0000
秩: 2

逆矩阵 A^(-1):
[[ 0.6 -0.7]
 [-0.2  0.4]]

是否为单位矩阵: True

利用逆矩阵求解方程组

Listing 13
import numpy as np

A = np.array([[4, 7], [2, 6]])
A_inv = np.linalg.inv(A)

# 方程组 Ax = b,解为 x = A^(-1) × b
b = np.array([1, 2])
x = A_inv @ b
print(f'方程组Ax=b的解: {x}')
方程组Ax=b的解: [-0.8  0.6]

数值稳定性提示:接近奇异的矩阵(行列式接近0)会导致数值不稳定。在金融中,协方差矩阵接近奇异意味着存在高度相关的资产。

特征值与特征向量:定义

对于方阵 \(\mathbf{A}\),若存在非零向量 \(\mathbf{v}\) 和标量 \(\lambda\) 使得:

\[ \large{\mathbf{Av} = \lambda\mathbf{v}} \]

\(\lambda\)特征值\(\mathbf{v}\)特征向量

金融应用

  • 主成分分析(PCA):降维和因子提取
  • 协方差矩阵对角化:找到不相关的风险因子
  • 马尔可夫链:稳态分布计算

特征值分解与主成分分析(PCA)

Listing 14
import numpy as np

cov_matrix = np.array([
    [0.0100, 0.0018, 0.0011],
    [0.0018, 0.0081, 0.0009],
    [0.0011, 0.0009, 0.0064]
])

# eigh:对称矩阵的特征值分解(特征值升序排列)
eigenvalues, eigenvectors = np.linalg.eigh(cov_matrix)

print('特征值:')
for i, val in enumerate(eigenvalues):
    print(f'  λ{i+1} = {val:.6f}')

# 解释方差比例
explained_var_ratio = eigenvalues / eigenvalues.sum()
print(f'\n解释方差比例:')
for i, ratio in enumerate(explained_var_ratio):
    print(f'  PC{i+1}: {ratio:.2%}')

# 累计解释方差
cumulative_var = np.cumsum(explained_var_ratio)
print(f'\n累计解释方差:')
for i, cum_var in enumerate(cumulative_var):
    print(f'  前{i+1}个主成分: {cum_var:.2%}')
特征值:
  λ1 = 0.005973
  λ2 = 0.007051
  λ3 = 0.011476

解释方差比例:
  PC1: 24.38%
  PC2: 28.78%
  PC3: 46.84%

累计解释方差:
  前1个主成分: 24.38%
  前2个主成分: 53.16%
  前3个主成分: 100.00%

广义逆矩阵(伪逆)

对于非方阵或奇异矩阵,使用 Moore-Penrose 伪逆 求最小二乘解。

Listing 15
import numpy as np

# 超定系统:4个方程,2个未知数
A = np.array([[1, 2], [3, 4], [5, 6], [7, 8]])
b = np.array([1, 2, 3, 4])

# Moore-Penrose伪逆
A_pinv = np.linalg.pinv(A)

# 最小二乘解:最小化 ||Ax - b||²
x = A_pinv @ b
print(f'最小二乘解: {x}')

# 残差与均方误差
residual = b - (A @ x)
mse = np.mean(residual ** 2)
print(f'均方误差: {mse:.6f}')
最小二乘解: [-4.4408921e-16  5.0000000e-01]
均方误差: 0.000000

本章小结

操作 函数/运算符 用途
矩阵乘法 @ / np.matmul() 投资组合计算
协方差矩阵 np.cov() 风险度量
线性方程组 np.linalg.solve() 因子收益求解
逆矩阵 np.linalg.inv() 方程组求解
特征值分解 np.linalg.eigh() PCA降维
伪逆 np.linalg.pinv() 最小二乘回归